package com.information.service.impl;

import com.information.service.IpBlacklistService;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.atomic.AtomicBoolean;

@Service
public class IpBlacklistServiceImpl implements IpBlacklistService {

    @Value("${app.blacklist.file-path:blacklist.txt}")
    private String blacklistFilePath;

    private final ReadWriteLock lock = new ReentrantReadWriteLock();
    private Set<String> blacklistedIps = new HashSet<>();
    private final AtomicBoolean saveInProgress = new AtomicBoolean(false);
    
    @PostConstruct
    public void init() {
        loadBlacklistFromFile();
    }
    
    private void loadBlacklistFromFile() {
        lock.writeLock().lock();
        try {
            Path path = Paths.get(blacklistFilePath);
            if (!Files.exists(path)) {
                Files.createFile(path);
            }
            
            blacklistedIps.clear();
            List<String> lines = Files.readAllLines(path);
            for (String line : lines) {
                String ip = line.trim();
                if (!ip.isEmpty() && !ip.startsWith("#")) {
                    blacklistedIps.add(ip);
                }
            }
        } catch (IOException e) {
            System.err.println("加载黑名单文件失败: " + e.getMessage());
        } finally {
            lock.writeLock().unlock();
        }
    }
    
    private void saveBlacklistToFile() {
        // 使用异步保存，避免阻塞主线程
        if (saveInProgress.compareAndSet(false, true)) {
            CompletableFuture.runAsync(() -> {
                lock.readLock().lock();
                try {
                    Path path = Paths.get(blacklistFilePath);
                    List<String> lines = new ArrayList<>(blacklistedIps);
                    Files.write(path, lines);
                } catch (IOException e) {
                    System.err.println("保存黑名单文件失败: " + e.getMessage());
                } finally {
                    lock.readLock().unlock();
                    saveInProgress.set(false);
                }
            });
        }
    }
    
    @Override
    public List<String> getAllBlacklistedIps() {
        lock.readLock().lock();
        try {
            return new ArrayList<>(blacklistedIps);
        } finally {
            lock.readLock().unlock();
        }
    }
    
    @Override
    public void addToBlacklist(String ipAddress, String operatedBy) {
        if (ipAddress == null || ipAddress.trim().isEmpty()) {
            throw new RuntimeException("IP地址不能为空");
        }
        
        String ip = ipAddress.trim();
        lock.writeLock().lock();
        try {
            if (blacklistedIps.contains(ip)) {
                throw new RuntimeException("IP地址已在黑名单中: " + ip);
            }
            blacklistedIps.add(ip);
            saveBlacklistToFile();
        } finally {
            lock.writeLock().unlock();
        }
    }
    
    @Override
    public void removeFromBlacklist(String ipAddress, String operatedBy) {
        if (ipAddress == null || ipAddress.trim().isEmpty()) {
            throw new RuntimeException("IP地址不能为空");
        }
        
        String ip = ipAddress.trim();
        lock.writeLock().lock();
        try {
            if (!blacklistedIps.contains(ip)) {
                throw new RuntimeException("IP地址不在黑名单中: " + ip);
            }
            blacklistedIps.remove(ip);
            saveBlacklistToFile();
        } finally {
            lock.writeLock().unlock();
        }
    }
    
    @Override
    public boolean isBlacklisted(String ipAddress) {
        if (ipAddress == null || ipAddress.trim().isEmpty()) {
            return false;
        }
        
        lock.readLock().lock();
        try {
            return blacklistedIps.contains(ipAddress.trim());
        } finally {
            lock.readLock().unlock();
        }
    }
}